package com.asiainfo.test.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;

import javax.sql.DataSource;
import java.util.Map;

import static com.asiainfo.test.config.DataSourceAutoConfig.getDataSource;
import static com.asiainfo.test.config.DataSourceAutoConfig.getDataSourceBeanName;
import static com.asiainfo.test.config.DataSourceProperties.isPrimary;

@Configuration
@Import({DataSourceAutoConfig.class, SqlSessionDaoAutoConfig.Registrar.class})
public class SqlSessionDaoAutoConfig {

    static class Registrar implements ImportBeanDefinitionRegistrar {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
                                            BeanDefinitionRegistry registry) {
            DataSourceProperties.get().forEach((name, value) -> {
                boolean primary = isPrimary(value);
                registry.registerBeanDefinition(name,
                        BeanDefinitionBuilder
                                .rootBeanDefinition(SqlSessionFactoryBeanFactory.class, "createInstance")
                                .addDependsOn(getDataSourceBeanName(name))
                                .addConstructorArgValue(name)
                                .setPrimary(primary)
                                .getBeanDefinition()
                );
            });
        }
    }

    static class SqlSessionFactoryBeanFactory {

        public static SqlSessionTemplate createInstance(String name) throws Exception {
            DataSourceProperties properties = DataSourceProperties.get();
            Map<String, Object> args = properties.get(name);
            SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
            String dataSourceBeanName = getDataSourceBeanName(name);
            DataSource dataSource = getDataSource(dataSourceBeanName);
            factory.setDataSource(dataSource);
            factory.setVfs(SpringBootVFS.class);
            factory.setMapperLocations(
                    new PathMatchingResourcePatternResolver()
                            .getResources(args.getOrDefault("mapperLocation",
                                    "classpath*:sql/**/*.xml").toString())
            );
            SqlSessionFactory sessionFactory = factory.getObject();
            return new SqlSessionTemplate(sessionFactory);
        }
    }

}
